package main

import (
	"embed"
	"flag"
	"html/template"
	"io/fs"
	"log"
	"minipromgr/internal/database"
	"minipromgr/internal/handlers"
	"minipromgr/internal/middleware"
	"minipromgr/internal/models"
	"net/http"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

//go:embed web/templates
var templatesFS embed.FS

//go:embed web/static/*
var staticFS embed.FS

// loadTemplatesForEmbed 加载嵌入的模板文件
func loadTemplatesForEmbed(r *gin.Engine) {
	// 使用嵌入的模板文件系统
	pattern := "web/templates/*"
	LoadHTMLFromEmbedFS(r, templatesFS, pattern)
}

func LoadHTMLFromEmbedFS(engine *gin.Engine, embedFS embed.FS, pattern string) {
	root := template.New("")
	tmpl := template.Must(root, LoadAndAddToRoot(engine.FuncMap, root, embedFS, pattern))
	engine.SetHTMLTemplate(tmpl)
}

// Method version
// func (engine *gin.Engine) LoadHTMLFromFS(embedFS embed.FS, pattern string) {
// 	root := template.New("")
// 	tmpl := template.Must(root, LoadAndAddToRoot(engine.FuncMap, root, embedFS, pattern))
// 	engine.SetHTMLTemplate(tmpl)
// }

func LoadAndAddToRoot(funcMap template.FuncMap, rootTemplate *template.Template, embedFS embed.FS, pattern string) error {
	pattern = strings.ReplaceAll(pattern, ".", "\\.")
	pattern = strings.ReplaceAll(pattern, "*", ".*")

	err := fs.WalkDir(embedFS, ".", func(path string, d fs.DirEntry, walkErr error) error {
		if walkErr != nil {
			return walkErr
		}

		if matched, _ := regexp.MatchString(pattern, path); !d.IsDir() && matched {
			data, readErr := embedFS.ReadFile(path)
			if readErr != nil {
				return readErr
			}
			// 使用文件名作为模板名称，而不是完整路径
			templateName := filepath.Base(path)
			t := rootTemplate.New(templateName).Funcs(funcMap)
			if _, parseErr := t.Parse(string(data)); parseErr != nil {
				return parseErr
			}
		}
		return nil
	})
	return err
}

// processDbPath 处理数据库路径
func processDbPath(dbPath string) string {
	// 检查是否为绝对路径
	if filepath.IsAbs(dbPath) {
		// 绝对路径，检查是否为目录
		if info, err := os.Stat(dbPath); err == nil && info.IsDir() {
			// 是目录，使用目录下的minipromgr.db
			return filepath.Join(dbPath, "minipromgr.db")
		}
		// 是文件或不存在，直接使用
		return dbPath
	}

	// 相对路径，检查是否为目录
	if info, err := os.Stat(dbPath); err == nil && info.IsDir() {
		// 是目录，使用目录下的minipromgr.db
		return filepath.Join(dbPath, "minipromgr.db")
	}

	// 是文件或不存在，直接使用
	return dbPath
}

// processUploadsPath 处理上传目录路径
func processUploadsPath(uploadsPath string) string {
	// 检查是否为绝对路径
	if !filepath.IsAbs(uploadsPath) {
		log.Printf("警告: 上传目录 '%s' 不是绝对路径，建议使用绝对路径以避免问题", uploadsPath)
	}

	// 确保目录存在
	if err := os.MkdirAll(uploadsPath, 0755); err != nil {
		log.Fatal("Failed to create uploads directory:", err)
	}

	return uploadsPath
}

// loadTemplates 加载模板文件
func loadTemplates(r *gin.Engine) {
	// 直接使用嵌入的模板文件系统
	loadTemplatesForEmbed(r)
}

func main() {
	// 解析命令行参数
	port := flag.String("port", "8080", "服务器端口号")
	dbPath := flag.String("db", "minipromgr.db", "数据库文件路径（文件或目录）")
	uploadsPath := flag.String("u", "uploads", "上传文件目录路径")
	flag.Parse()

	// 显示帮助信息
	if flag.NFlag() == 0 {
		log.Println("MiniPromgr - 简易项目管理工具")
		log.Println("使用方法:")
		log.Println("  ./minipromgr-dev                                    # 使用默认配置")
		log.Println("  ./minipromgr-dev -port 3000                        # 指定端口")
		log.Println("  ./minipromgr-dev -db /opt/data/mymgr.db            # 指定数据库文件")
		log.Println("  ./minipromgr-dev -db /opt/data/                    # 指定数据库目录")
		log.Println("  ./minipromgr-dev -u /opt/uploads                   # 指定上传目录")
		log.Println("  ./minipromgr-dev -port 3000 -db /opt/data -u /opt/uploads  # 组合使用")
		log.Println("")
	}

	// 处理数据库路径
	finalDbPath := processDbPath(*dbPath)
	log.Printf("使用数据库文件: %s", finalDbPath)

	// 处理上传目录路径
	finalUploadsPath := processUploadsPath(*uploadsPath)
	log.Printf("使用上传目录: %s", finalUploadsPath)

	// 设置上传路径
	handlers.SetUploadsPath(finalUploadsPath)

	// 初始化数据库
	db, err := database.InitDBWithPath(finalDbPath)
	if err != nil {
		log.Fatal("Failed to initialize database:", err)
	}

	// 自动迁移数据库表
	err = db.AutoMigrate(&models.User{}, &models.Project{}, &models.Item{}, &models.Picture{})
	if err != nil {
		log.Fatal("Failed to migrate database:", err)
	}

	// 设置models包的GetDB函数
	models.SetGetDBFunc(func() *gorm.DB {
		return db
	})

	// 初始化默认数据
	database.InitDefaultData(db)

	// 创建Gin引擎
	r := gin.Default()

	// 静态文件服务
	r.StaticFS("/static", http.FS(staticFS))

	// 模板服务
	loadTemplates(r)

	// 中间件
	r.Use(middleware.CORSMiddleware())

	// 路由组
	api := r.Group("/api")
	{
		// 认证相关
		api.POST("/login", handlers.Login)
		api.POST("/logout", handlers.Logout)

		// Item相关（替代Bug）
		items := api.Group("/items")
		items.Use(middleware.AuthMiddleware())
		{
			items.GET("", handlers.GetItems)
			items.POST("", handlers.CreateItem)
			items.GET("/:id", handlers.GetItem)
			items.PUT("/:id", handlers.UpdateItem)
			items.DELETE("/:id", handlers.DeleteItem)
			items.POST("/:id/images", handlers.AssociateImagesWithItem)
		}

		// 项目相关
		projects := api.Group("/projects")
		projects.Use(middleware.AuthMiddleware())
		{
			projects.GET("", handlers.GetProjects)
			projects.POST("", handlers.CreateProject)
			projects.POST("/:id/archive", handlers.ArchiveProject) // 放在 /:id 路由之前
			projects.GET("/:id", handlers.GetProject)
			projects.PUT("/:id", handlers.UpdateProject)
			projects.DELETE("/:id", handlers.DeleteProject)
		}

		// 图片上传
		api.POST("/upload", middleware.AuthMiddleware(), handlers.UploadImage)
		api.GET("/images/:filename", handlers.GetImage)
		api.DELETE("/images/:id", middleware.AuthMiddleware(), handlers.DeleteImage)
	}

	// Web页面路由
	r.GET("/", handlers.Dashboard)
	r.GET("/login", handlers.LoginPage)
	r.GET("/dashboard", middleware.AuthMiddleware(), handlers.Dashboard)
	r.GET("/projects/:id", middleware.AuthMiddleware(), handlers.ProjectDetailPage)
	r.GET("/items/:id", middleware.AuthMiddleware(), handlers.ItemDetailPage)
	r.GET("/items/:id/edit", middleware.AuthMiddleware(), handlers.EditItemPage)
	r.GET("/items/new", middleware.AuthMiddleware(), handlers.NewItemPage)
	r.GET("/test-paste", handlers.TestPastePage)

	log.Printf("Server starting on :%s", *port)
	r.Run(":" + *port)
}
